/*****************************************************************************
 * file  : systask.c
 * creat : apleilx
 * data  : 2017/11/05
 *******************************************************************************/
#include "os_obj.h"
#include "sys_task.h"
#include "pincfg.h"
#include "framework.h"
#include "src/rfid_utils.h"

/*****************************************************************************
 * @brief   fun.
 *****************************************************************************/
uint8_t ext_spi_rw(uint8_t dataw);
void ic_card_opt(void);

/*****************************************************************************
 * @brief   var.
 *****************************************************************************/

/*******************************************************************************
 * @brief: init
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
void rc522_spi_read(uu08 *buff, uu08 addr, uu08 len, uu08 addr_inc)
{
	int index;

	rfid_cs.dis();

	ext_spi_rw(_BIT(7) | (addr << 1));

	for (index = 0; index < len; index++)
	{
		addr += addr_inc;
		buff[index] = ext_spi_rw(_BIT(7) | (addr << 1));
	}

	buff[index] = ext_spi_rw(0);

	rfid_cs.en();
}

void rc522_spi_write(uu08 *buff, uu08 addr, uu08 len)
{
	int index;

	rfid_cs.dis();

	ext_spi_rw(addr << 1);

	for (index = 0; index < len; index++)
	{
		ext_spi_rw(buff[index]);
	}

	rfid_cs.en();
}

/*******************************************************************************
 * @brief: init
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int rc522_init(int argc, char *argv[])
{
	uu08 buff[80];
	int index;

	rfid_cs.dir_out_pp();
	rfid_rst.dir_out_pp();

	rfid_cs.en();
	rfid_rst.dis();
	osDelay(ms_ticks(100));
	rfid_rst.en();
	osDelay(ms_ticks(200));

	dbg_puts("init end! \n");

	return 0;
}
DBG_FUN_EXPORT(rc522_init);

/*******************************************************************************
 * @brief: rc522 register read
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int rc522_reg_read(int argc, char *argv[])
{
	uu08 buff[80];
	int index;
	uu08 addr = 0;
	uu08 len = 1;
	uu08 addr_inc = 0;

	if (argc > 1)
		addr = atoi(argv[1]);

	if (argc > 2)
		len = atoi(argv[2]);

	if (argc > 3)
		addr_inc = atoi(argv[3]);

	rc522_spi_read(buff, addr, len, addr_inc);

	dbg_u8_print("rc522 reg read:\n", buff, len, 16);

	dbg_puts(SYMBOL_LINE_DOT PTCR);
	return 0;
}
DBG_FUN_EXPORT(rc522_reg_read);

/*******************************************************************************
 * @brief: rc522 register write
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int rc522_reg_write(int argc, char *argv[])
{
	uu08 buff[80];
	int index;
	uu08 addr = 0;
	uu08 len = 0;

	if (argc < 3)
		return 1;

	addr = atoi(argv[1]);
	len = ascii_to_hex2_multi(argv[2], buff, 80);

	rc522_spi_write(buff, addr, len);

	dbg_u8_print("rc522 reg write:\n", buff, len, 16);

	dbg_puts(SYMBOL_LINE_DOT PTCR);
	return 0;
}
DBG_FUN_EXPORT(rc522_reg_write);

/*******************************************************************************
 * @brief: rc522 lib hal
 * @param none
 * @return none
 ******************************************************************************/
void MFRC522_SS_enable(void)
{
	rfid_cs.dis();
}

void MFRC522_SS_disable(void)
{
	rfid_cs.en();
}

void MFRC522_RST_enable(void)
{
	rfid_rst.dis();
}

void MFRC522_RST_disable(void)
{
	rfid_rst.en();
}

const struct MFRC522_HAL_T rc522_hal = {
	MFRC522_SS_enable, // 片选生效
	MFRC522_SS_disable, // 片选取消
	MFRC522_RST_enable, // 复位生效
	MFRC522_RST_disable, // 复位取消
	ext_spi_rw}; // SPI读写

/*******************************************************************************
 * @brief: rc522 lib app
 ******************************************************************************/
struct MFRC522_T rfid_obj;
int last_balance = 0;
unsigned int last_user_ID;
uu08 rc522_scan_en = 0;
uu08 rc522_scan_mode = 0;
	
#define MIN_BALANCE 300

/*******************************************************************************
 * @brief: rc522 lib start
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int rc522_lib_init(int argc, char *argv[])
{
	uu08 buff[80];

	rfid_cs.dir_out_pp();
	rfid_rst.dir_out_pp();
	
	rc522_scan_mode = 0;
	
	if(argc > 1)
	{
		if(argv[1][0] == 'w')
			rc522_scan_mode = 1;
	}

	rfid_obj.hal = &rc522_hal;

	setupRFID(&rfid_obj);

	rc522_scan_en = 1;

	dbg_puts(SYMBOL_LINE_DOT PTCR);
	return 0;
}
DBG_FUNX_EXPORT(rc522_lib_init, "[r/w]");

/*******************************************************************************
 * @brief: rc522 scan
 * @param none
 * @return none
 ******************************************************************************/
void MFRC522_scan(void)
{
	if (rc522_scan_en)
	{
		// Look for new cards in RFID2
		if (PICC_IsNewCardPresent(&rfid_obj))
		{
			// Select one of the cards
			if (PICC_ReadCardSerial(&rfid_obj))
			{
				// int status = writeCardBalance(rfid_obj, 100000); // used to recharge the card
				ic_card_opt();
			}
		}
	}
}
obj_app_order(MFRC522_scan);

/*******************************************************************************
 * @brief: rc522 opt
 * @param none
 * @return none
 ******************************************************************************/
void ic_card_opt(void)
{
	//	show card UID
	dbg_print("\nCard uid bytes: ");
	for (uint8_t i = 0; i < rfid_obj.uid.size; i++)
	{
		dbg_print(" %X", rfid_obj.uid.uidByte[i]);
	}
	dbg_print("\n\r");

	// Convert the uid bytes to an integer, byte[0] is the MSB
	last_user_ID =
		(int)rfid_obj.uid.uidByte[3] |
		(int)rfid_obj.uid.uidByte[2] << 8 |
		(int)rfid_obj.uid.uidByte[1] << 16 |
		(int)rfid_obj.uid.uidByte[0] << 24;

	dbg_print("\nCard Read user ID: %X ", last_user_ID);

	if(0 == rc522_scan_mode)
	{
		// Read the user balance
		last_balance = readCardBalance(&rfid_obj);

		if (last_balance == (-999))
		{
			// Error handling, the card does not have proper balance data inside
		}
		else
		{
			// Check for minimum balance
			if (last_balance < MIN_BALANCE)
			{
				dbg_print("%08X, Insufficient balance\n", last_balance);
			}
			else
			{
				dbg_print("%08X, Balance OK\n", last_balance);
			}
		}
	}
	else
	{
		writeCardBalance(&rfid_obj, 0);
	}
	dbg_puts(SYMBOL_LINE_ADD PTCR);
}
